package com.sojson.config.mybatis.aspect;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import com.sojson.aspect.PointcutsBase;
import com.sojson.base.impl.BaseListDto;
import com.sojson.base.impl.BaseUser;
import com.sojson.config.mybatis.annotation.DataScope;
import com.sojson.constant.Constant;
import com.sojson.constant.ConstantServlet;
import com.sojson.constant.DataScopeType;
import com.sojson.util.StringUtil;
import com.sojson.util.param.ParamUtil;
import com.sojson.util.token.TokenUtil;

/**
 * 数据过滤处理
 *
 * @author lyh
 */
@Aspect
@Component
public class DataScopeAspect implements PointcutsBase {

    /** 数据权限过滤关键字 */
    /** 权限类型 */
    public static final String DATA_SCOPE = "DATA_SCOPE";
    /** 部门表别名 */
    public static final String DEPT_ALIAS = "DEPT_ALIAS";
    /** 部门表字段名 */
    public static final String DEPT_FIELD = "DEPT_FIELD";
    /** 部门是否查询为空的 */
    public static final String DEPT_IS_NULL = "DEPT_IS_NULL";
    /** 部门为个人权限是否查询为空的 */
    public static final String DEPT_SELF_IS_NULL = "DEPT_SELF_IS_NULL";
    /** 部门列表 */
    public static final String DEPTS = "DEPTS";
    /** 用户表别名 */
    public static final String USER_ALIAS = "USER_ALIAS";
    /** 用户表字段名 */
    public static final String USER_FIELD = "USER_FIELD";
    /** 用户是否查自己的 */
    public static final String USER_IS_THIS = "USER_IS_THIS";
    /** 用户是否查询为空的 */
    public static final String USER_IS_NULL = "USER_IS_NULL";
    /** 用户编号 */
    public static final String USER = "USER";
    /** 角色表别名 */
    public static final String ROLE_ALIAS = "ROLE_ALIAS";
    /** 角色表字段名 */
    public static final String ROLE_FIELD = "ROLE_FIELD";
    /** 角色列表 */
    public static final String ROLES = "ROLES";
    private static final String ANNO_PACKAGE_PATH = ConstantServlet.PACKAGE_DEFAULT_BASE + ".config.mybatis.annotation";

    @Pointcut("@annotation(" + ANNO_PACKAGE_PATH + ".DataScope) && (" + POINT_SERVICE + ")")
    public void pointCutAnno() {}

    /** 配置织入点 */
    @Before("pointCutAnno()")
    public void doBefore(JoinPoint point) throws Throwable {
        handleDataScope(point);
    }

    /**
     * 处理方法
     * 
     * @param joinPoint
     * @throws IOException
     */
    protected void handleDataScope(final JoinPoint joinPoint) throws IOException {
        // 获得注解
        DataScope controllerDataScope = getAnnotationLog(joinPoint);
        if (controllerDataScope.isDefault()) {
            return;
        }

        // 获取当前的用户
        boolean login = ParamUtil.isLogin();
        if (login) {
            BaseUser user = TokenUtil.getUser();
            // 如果是超级管理员，则不过滤数据
            if (!ParamUtil.isAdminSuper()) {
                dataScopeFilter(joinPoint, user, controllerDataScope);
            }
        }
    }

    /**
     * 数据范围过滤
     *
     * @param joinPoint 切点
     * @param user      用户
     * @param dataScope 权限注解
     * @throws IOException 
     */
    public static void dataScopeFilter(JoinPoint joinPoint, BaseUser user, DataScope dataScope) throws IOException {
        Object params = joinPoint.getArgs()[0];
        if (StringUtil.isBlankObject(params) || !(params instanceof BaseListDto)) {
            return;
        }

        Integer scope = user.getDataScope();
        BaseListDto baseEntity = (BaseListDto)params;
        Map<String, Object> perms = baseEntity.getParams();
        perms.put(DATA_SCOPE, scope);

        // 部门权限
        String deptField = dataScope.deptField();
        if (StringUtil.isNotBlank(deptField)) {
            if (DataScopeType.DATA_SCOPE_CUSTOM == scope) {
                perms.put(DEPTS, TokenUtil.getDepts());
            } else if (DataScopeType.DATA_SCOPE_DEPT == scope) {
                Set<String> depts = new HashSet<>();
                depts.add(user.getDeptId());
                perms.put(DEPTS, depts);
            } else if (DataScopeType.DATA_SCOPE_DEPT_AND_CHILD == scope) {
                perms.put(DEPTS, TokenUtil.getDepts());
            }
            buildDeptColumn(dataScope, perms);
        }

        // 个人权限
        String userField = dataScope.userField();
        if (StringUtil.isNotBlank(userField)) {
            perms.put(USER, user.getId());
            buildUserColumn(dataScope, perms);
        }

        // 角色权限
        String roleField = dataScope.roleField();
        if (StringUtil.isNotBlank(roleField)) {
            perms.put(ROLES, dataScope.roleIsAll() ? TokenUtil.getToken().getRoleIdsExist() : TokenUtil.getRoleIds());
            buildRoleColumn(dataScope, perms);
        }
    }

    /**
     * 构建部门Column
     * 
     * @param dataScope 权限注解
     * @param perms     权限列表
     * @return
     */
    public static void buildDeptColumn(DataScope dataScope, Map<String, Object> perms) {
        String alias = dataScope.deptAlias();
        if (StringUtil.isNotBlank(alias)) {
            perms.put(DEPT_ALIAS, alias + Constant.JH);
        }
        String field = dataScope.deptField();
        if (StringUtil.isNotBlank(field)) {
            perms.put(DEPT_FIELD, field);
        }
        perms.put(DEPT_IS_NULL, dataScope.deptIsNull());
    }

    /**
     * 构建用户Column
     * 
     * @param dataScope 权限注解
     * @param perms     权限列表
     * @return
     */
    public static void buildUserColumn(DataScope dataScope, Map<String, Object> perms) {
        String alias = dataScope.userAlias();
        if (StringUtil.isNotBlank(alias)) {
            perms.put(USER_ALIAS, alias + Constant.JH);
        }
        String field = dataScope.userField();
        if (StringUtil.isNotBlank(field)) {
            perms.put(USER_FIELD, field);
        }
        perms.put(DEPT_SELF_IS_NULL, dataScope.deptSelfIsNull());
        perms.put(USER_IS_THIS, dataScope.userIsThis());
        perms.put(USER_IS_NULL, dataScope.userIsNull());
    }

    /**
     * 构建角色Column
     * 
     * @param dataScope 权限注解
     * @param perms     权限列表
     * @return
     */
    public static void buildRoleColumn(DataScope dataScope, Map<String, Object> perms) {
        String alias = dataScope.roleAlias();
        if (StringUtil.isNotBlank(alias)) {
            perms.put(ROLE_ALIAS, alias + Constant.JH);
        }
        String field = dataScope.roleField();
        if (StringUtil.isNotBlank(field)) {
            perms.put(ROLE_FIELD, field);
        }
    }

    /**
     * 是否存在注解，如果存在就获取
     * 
     * @param joinPoint
     * @return
     */
    private DataScope getAnnotationLog(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature)signature;
        Method method = methodSignature.getMethod();

        if (method != null) {
            return method.getAnnotation(DataScope.class);
        }
        return null;
    }

}